#!/usr/bin/env python
# coding: utf-8
# author: Wesley

import json
import time
from django.http import JsonResponse

from lib.alipay_v2 import utils as alipay
from lib.common import AbstractHandler
from lib.wxpay.wxpay import WeChatPay
from project.settings_common import IOS_Goods, USER_LEVEL
from services.datamodel.course.models import mm_Course
from services.datamodel.delivery.models import mm_Delivery
from services.datamodel.evaluation.models import mm_Evaluation
from services.datamodel.order.models import mm_Order
from services.datamodel.role.models import mm_Role
from services.datamodel.student.models import mm_Student
from services.datamodel.live.models import mm_LiveGoods, mm_LiveGoodsSku, mm_Live
import datetime

class BaseHandler(AbstractHandler):
    PRODUCT_DESC_PREFIX = "亿教亿学出品："
    PURCHASE_TYPE_ALIPAY = 1  # 支付宝支付
    PURCHASE_TYPE_WECHAT = 2  # 微信支付
    PURCHASE_TYPE_APPLE = 3  # 苹果支付
    PURCHASE_FROM_APP = 1  # app支付
    PURCHASE_FROM_WEB = 2  # web支付

    GOODS_TYPE_ROLE = 1  # 会员
    GOODS_TYPE_COURSE = 2  # 课程
    GOODS_TYPE_CEPIN = 3  # 测评
    GOODS_TYPE_DELIVERY = 4  # 测评
    GOODS_TYPE_IOS = 99  # ios提审专用

    # 订单支付状态
    TRADE_STATUS_UNPAY = 1  # 未支付
    TRADE_STATUS_PAID = 2  # 已支付
    TRADE_STATUS_BACK = 3  # 已退款

    def __init__(self, app_logger):
        AbstractHandler.__init__(self, app_logger)

    def create_yijiao_tradeno(self, userId, producttype=None, productid=None, str_ppis=None):
        """
        :param userId: 如果是亿教会员类产品，这个userId必须是学生的user id，不管是学生购买还是家长帮学生购买的
        :param producttype:
        :param productid:
        :param str_ppis:套餐id
        :return:
        """
        if all((producttype, productid, str_ppis)):
            return "%s_%s_%s_%s_%s" % (userId, str(int(time.time())), producttype, productid, str_ppis)
        else:
            return "%s_%s" % (userId, str(int(time.time())))

    def product_purchase(self, uid, goods_type, goods_id, paytype=1, payfrom=None, buyer_type='student',
                         client_ip=None, mweb=0, openid=0, check_price=0, buyer_user=None, share_code=None,
                         sku_id=None, address=None, live_id=None):

        if goods_type == self.GOODS_TYPE_ROLE:
            product = mm_Role.get_or_default(id=goods_id)
        elif goods_type == self.GOODS_TYPE_IOS:
            product = IOS_Goods[goods_id]
        elif goods_type == self.GOODS_TYPE_CEPIN:
            product = mm_Evaluation.get_or_default(id=goods_id)
        elif goods_type == self.GOODS_TYPE_DELIVERY:
            product = mm_Delivery.get_or_default(id=goods_id)
        else:
            product = mm_Course.get_or_default(id=goods_id)
        if not product:
            return {'retcode': 1, 'msg': '产品不存在'}

        if goods_type == self.GOODS_TYPE_IOS:
            total_fee = product['price']
            tradeno = self.create_yijiao_tradeno(uid, goods_type, goods_id, 1)
            return self.user_purchase(goods_id, goods_type, tradeno, total_fee, product['name'], product['name'],
                                      paytype=paytype,
                                      payfrom=payfrom, buyer_type=buyer_type, client_ip=client_ip, mweb=mweb,
                                      openid=openid,
                                      studentid=uid, sku_id=sku_id, address=address, live_id=live_id)
        else:
            # 将以分为计算的钱数改为元为单位，保留2位小数位
            total_fee = round(product.charge / 100.0, 2)
            if live_id:
                live_obj = mm_Live.filter(pk=live_id).first()
                live_goods = mm_LiveGoods.get_or_default(live_id=live_id, goods_id=goods_id)
                date_now = datetime.datetime.now()
                if live_obj.discount_start_time and live_obj.discount_end_time and live_obj.discount_start_time <= date_now <= live_obj.discount_end_time:
                    total_fee = round(live_goods.charge / 100.0, 2)
                else:
                    total_fee = round(live_goods.goods.original_charge / 100.0, 2)
                if live_goods.stock <= 0:
                    return {'retcode': 1, 'msg': '产品库存不足'}
                if sku_id:
                    skuObj = mm_LiveGoodsSku.get_or_default(id=sku_id)
                    if live_obj.discount_start_time and live_obj.discount_end_time and live_obj.discount_start_time <= date_now <= live_obj.discount_end_time:
                        total_fee = round(skuObj.charge / 100.0, 2)
                    else:
                        total_fee = round(live_goods.goods.original_charge / 100.0, 2)
                    if skuObj.stock <= 0:
                        return {'retcode': 1, 'msg': '产品库存不足'}

            tradeno = self.create_yijiao_tradeno(uid, goods_type, goods_id, 1)
            return self.user_purchase(goods_id, goods_type, tradeno, total_fee, product.name, product.name, paytype=paytype,
                                      payfrom=payfrom, buyer_type=buyer_type, client_ip=client_ip, mweb=mweb, openid=openid,
                                      studentid=uid, share_code=share_code, sku_id=sku_id, address=address, live_id=live_id)

    # def u_proxy_purchase(self, user, detail, client_ip, openid):
    #     """
    #     'product_id', 'address', 'phone', 'nickname', 'province_code', 'city_code', 'district_code',
    #                      buyer_id, goods_list
    #     """
    #     uid = user.id
    #     detail['buyer_id'] = user.id
    #     detail['province_code'], detail['city_code'], detail['district_code'] = user.student.provinceid, \
    #         user.student.cityid, user.student.districtid
    #     province_code = user.student.provinceid
    #     price = detail['price']
    #
    #     p_obj = mm_Product.filter(producttype=8).last()
    #     assert p_obj, (1, '商品未配置')
    #
    #     p_content = json.loads(p_obj.content)
    #     # 將days 在這裏存放，最後回調可以節省一次db獲取
    #     detail['days'] = p_content.get('days', 180)
    #     r_p = p_content[province_code] if p_content.get(province_code) else p_content['price']
    #
    #     if not p_obj:
    #         return {'retcode': 1, 'msg': '商品未配置'}
    #     if float(price) != r_p:
    #         return {'retcode': 1, 'msg': '金额或选择数量有误'}
    #
    #     tradeno = self.create_yijiao_tradeno(uid, mm_Product.PRODUCT_TYPE_TO_PROXY, p_obj.id, "0")
    #
    #     return self.user_purchase_u_proxy(detail, tradeno, price, client_ip, openid)

    # def bee_purchase(self, user, detail, client_ip, openid):
    #     """
    #     'product_id', 'address', 'phone', 'nickname', 'province_code', 'city_code', 'district_code',
    #                      buyer_id, goods_list
    #     """
    #     uid = user.id
    #     detail['buyer_id'] = user.id
    #     content = detail['content']
    #     detail['province_code'], detail['city_code'], detail['district_code'] = user.student.provinceid, \
    #         user.student.cityid, user.student.districtid
    #     # province_code = user.student.provinceid
    #     price = detail['price']
    #     content1 = {}
    #     for item, value in content.items():
    #         content1[item] = [i.replace("<br/>", "").replace(" ", "") for i in value]
    #
    #     tradeno = self.create_yijiao_tradeno(uid, mm_Product.PRODUCT_TYPE_BEE_PROXY, detail['product_id'], "0")
    #
    #     return self.user_purchase_u_proxy(detail, tradeno, price, client_ip, openid, body=json.dumps(content1))

    # def event_purchase(self, uid, detail, client_ip, openid):
    #
    #     product_id = detail['product_id']
    #     price = detail['price']
    #     content = detail['content']
    #     items = detail['items']
    #
    #     content1 = {}
    #     for item, value in content.items():
    #         content1[item] = [i.replace("<br/>", "").replace(" ", "") for i in value]
    #
    #     detail['buyer_id'] = uid
    #     r_p = round(float(sum(mm_SellEventItem.filter(id__in=items).values_list('price', flat=True))), 2)
    #     discount_info = mm_EventItemDiscount.get_info()['data']
    #     if discount_info:
    #         d = json.loads(mm_EventItemDiscount.get_info()['data'][0]['content'])
    #         d_s = max(filter(lambda i: i[0] <= r_p, d), default=[0, 100])[1] * 0.01
    #         r_p *= d_s
    #
    #     if float(price) != r_p:
    #         return {'retcode': 1, 'msg': '金额或选择数量有误'}
    #
    #     str_ppis = "0"
    #
    #     tradeno = self.create_yijiao_tradeno(uid, mm_Product.PRODUCT_TYPE_EVENT, product_id, str_ppis)
    #
    #     return self.user_purchase_tmp(detail, tradeno, price, content1, client_ip, openid)

    def user_purchase(self, product_id, product_type, tradeno, total_fee, title, body, paytype, payfrom, buyer_type,
                      client_ip, mweb, openid, studentid, share_code=None, sku_id=None, address=None, live_id=None):
        """
        :param share_code:
        :param product_id: role or courseid
        :param product_type: 产品类型，目前两种: 1 role; 2 course
        :param tradeno: 订单号
        :param total_fee: 总共金额数, 元
        :param title: 订单标题
        :param body: 订单内容
        :param paytype: 支付方式,1:支付宝 2:微信支付 3:苹果
        :param payfrom:支付请求来源，1：移动支付 2：WEB支付
        :param buyer_type: 微信需要不同的商户账号，所以要区别不同下单类型, 目前momself就一个
        :param client_ip: 客户机ip
        :param mweb: 1为手机web, 2为微信浏览器 0为pc
        :param openid: 微信公众号支付需要openid
        :param studentid, student表id
        :return:
        """
        if product_type in [self.GOODS_TYPE_ROLE, self.GOODS_TYPE_COURSE, self.GOODS_TYPE_IOS, self.GOODS_TYPE_CEPIN,
                            self.GOODS_TYPE_DELIVERY]:
            # 目前的虚拟产品

            if payfrom == self.PURCHASE_FROM_APP:  # 移动支付
                agent_id, proxy_id = 0, 0
                student = mm_Student.filter(pk=studentid).first()
                if student.level in [USER_LEVEL.LEVEL_SHENG, USER_LEVEL.LEVEL_SHI, USER_LEVEL.LEVEL_QU,
                                     USER_LEVEL.LEVEL_ENDORSEMENT, USER_LEVEL.LEVEL_OPERATOR,
                                     USER_LEVEL.LEVEL_PLATINUM]:
                    agent_id, proxy_id = studentid, studentid
                else:
                    directproxy = mm_Student.getDirectProxy(studentid)
                    if directproxy:
                        agent_id, proxy_id = directproxy.id, directproxy.id
                if product_type != self.GOODS_TYPE_IOS:
                    mm_Order.create(
                        user_id=studentid,
                        charge=total_fee * 100,
                        status=self.TRADE_STATUS_UNPAY,
                        order_no=tradeno,
                        payment=paytype,
                        payment_method=self.PURCHASE_FROM_APP,
                        agent_id=agent_id,
                        proxy_id=proxy_id,
                        goods_type=product_type,
                        goods_id=product_id,
                        goods_name=title,
                        sku_id=sku_id if sku_id else None,
                        address_id=address if address else None,
                        live_id=live_id if live_id else None
                    )
                if paytype == self.PURCHASE_TYPE_ALIPAY:  # 支付宝支付
                    params = alipay.app_pay(tradeno, total_fee, title)
                    return params
                elif paytype == self.PURCHASE_TYPE_WECHAT:  # 微信支付
                    payObj = WeChatPay(buyer_type)
                    params = payObj.build_form_by_params({
                        'body': body,
                        'out_trade_no': tradeno,
                        'total_fee': int(float(total_fee) * 100),  # 微信规定以分为单位
                        'spbill_create_ip': client_ip,
                    })
                    return {'retcode': 0, 'wechat_params': params, 'tradeno_yijiao': tradeno}

            else:  # WEB支付
                directproxy, old_status = mm_Student.getDirectProxy(studentid, needStatus=True)

                # 下面这几行是以前的逻辑，现在走的流量和销售分佣机制，暂时先注销
                # agentid = directproxy.id if directproxy else 0
                # if share_code:
                #     shareuser = mm_Student.filter(share_code=share_code).first()
                #     if (agentid > 0 and agentid != shareuser.id and old_status == 0) or agentid == 0:
                #         agentid = shareuser.id
                proxy_id = directproxy.id if directproxy else 0
                agent_id, cmaster_id = 0, 0
                if share_code:
                    shareuser = mm_Student.filter(share_code=share_code).first()
                    if shareuser:
                        if shareuser.level in [USER_LEVEL.LEVEL_SHENG, USER_LEVEL.LEVEL_SHI, USER_LEVEL.LEVEL_QU,
                                               USER_LEVEL.LEVEL_ENDORSEMENT, USER_LEVEL.LEVEL_OPERATOR,
                                               USER_LEVEL.LEVEL_PLATINUM]:
                            agent_id = shareuser.id
                        elif shareuser.level == USER_LEVEL.LEVEL_CLASSMASTER:
                            cmaster_id = shareuser.id
                        else:  # 如果是粉丝分享出的链接，销售依然算直接代理商的
                            agent_id = proxy_id
                    if proxy_id and not shareuser:
                        agent_id = proxy_id
                else:
                    agent_id = proxy_id  # 这里只要有上级就会绑定上级
                mm_Order.create(
                    user_id=studentid,
                    charge=total_fee * 100,
                    status=self.TRADE_STATUS_UNPAY,
                    order_no=tradeno,
                    payment=paytype,
                    payment_method=self.PURCHASE_FROM_WEB,
                    agent_id=agent_id,
                    proxy_id=proxy_id,
                    cmaster_id=cmaster_id,
                    goods_type=product_type,
                    goods_id=product_id,
                    goods_name=title,
                    sku_id=sku_id if sku_id else None,
                    address_id=address if address else None,
                    live_id=live_id if live_id else None
                )
                if paytype == self.PURCHASE_TYPE_ALIPAY:  # 支付宝支付
                    # alipayurl = alipay.create_direct_pay_by_user(tradeno, title, body, total_fee, 1, mweb)
                    if mweb == 1:
                        params = alipay.wap_pay(tradeno, total_fee, title)
                    else:
                        params = alipay.page_pay(tradeno, total_fee, title)
                    return params
                elif paytype == self.PURCHASE_TYPE_WECHAT:  # 微信支付
                    pre_params = {
                        'body': body,
                        'out_trade_no': tradeno,
                        'total_fee': int(float(total_fee) * 100),  # 微信规定以分为单位
                        'spbill_create_ip': client_ip,
                    }
                    # mobile浏览器&非微信浏览器
                    if mweb == 1:
                        payObj = WeChatPay('qrh5')
                    # mobile浏览器&微信浏览器
                    elif mweb == 2:
                        payObj = WeChatPay('mp')
                        pre_params['openid'] = openid
                    # PC浏览器
                    else:
                        payObj = WeChatPay('qrcode')
                    params = payObj.build_form_by_params(pre_params)
                    return {'retcode': 0, 'wechat_params': params, 'tradeno_yijiao': tradeno}

        # elif product_type in [mm_Product.PRODUCT_TYPE_ACTUAL, mm_Product.PRODUCT_TYPE_PROXY,
        #                       mm_Product.PRODUCT_TYPE_COMPANY, mm_Product.PRODUCT_TYPE_REAL,
        #                       mm_Product.PRODUCT_TYPE_EVENT]:  # 当前商品和以前衔接教材处理一致
        #     if payfrom == self.PURCHASE_FROM_APP:  # 移动支付
        #         if paytype == self.PURCHASE_TYPE_ALIPAY:  # 支付宝支付
        #             params = alipay.gen_mobilepay_params(tradeno, title, body, total_fee)
        #             mm_AliPayTrade.create(tradeno_yijiao=tradeno,
        #                                   total_fee=total_fee,
        #                                   details=json.dumps(detail),
        #                                   deal_status=mm_AliPayTrade.TRADE_STATUS_UNPAY)
        #             return {'retcode': 0, 'params': params}
        #         else:  # 微信支付
        #             payObj = WeChatPay(buyer_type)
        #             tradeObj = WeChatTrade(tradeno_yijiao=tradeno,
        #                                    body=body,
        #                                    deal_status=mm_WeChatTrade.TRADE_STATUS_UNPAY,
        #                                    total_fee=total_fee,
        #                                    trade_type='APP',
        #                                    fee_type='CNY',
        #                                    device_info='WEB',
        #                                    trade_address=detail['address'],
        #                                    trade_phone=detail['phone'],
        #                                    trade_nickname=detail['nickname'],
        #                                    province_code=detail['province_code'],
        #                                    city_code=detail['city_code'],
        #                                    district_code=detail['district_code'],
        #                                    invite_code=detail['invite_code'],
        #                                    couponid=detail['coupon_id'],
        #                                    buyer_id=detail['buyer_id'],
        #                                    order_detail=json.dumps(detail['order_detail'])
        #                                    )
        #             params = payObj.build_form_by_params({
        #                 'body': body,
        #                 'out_trade_no': tradeno,
        #                 'total_fee': int(float(total_fee) * 100),  # 微信规定以分为单位
        #                 'spbill_create_ip': client_ip,
        #             })
        #             if params:
        #                 tradeObj.save()
        #             return {'retcode': 0, 'wechat_params': params, 'tradeno_yijiao': tradeno}
        #     else:
        #         # 銜接教材相關邏輯
        #         if paytype == self.PURCHASE_TYPE_ALIPAY:  # 支付宝支付
        #             alipayurl = alipay.create_direct_pay_by_user(tradeno, title, body, total_fee, 1, mweb)
        #             mm_AliPayTrade.create(tradeno_yijiao=tradeno,
        #                                   total_fee=total_fee,
        #                                   details=json.dumps(detail),
        #                                   deal_status=mm_AliPayTrade.TRADE_STATUS_UNPAY)
        #             return {'retcode': 0, 'alipayurl': alipayurl, 'tradeno_yijiao': tradeno}
        #         elif paytype == self.PURCHASE_TYPE_WECHAT:  # 微信支付
        #             tradeObj = WeChatTrade(tradeno_yijiao=tradeno,
        #                                    body=body,
        #                                    deal_status=mm_WeChatTrade.TRADE_STATUS_UNPAY,
        #                                    total_fee=total_fee,
        #                                    trade_type='NATIVE',
        #                                    fee_type='CNY',
        #                                    device_info='WEB',
        #                                    trade_address=detail['address'],
        #                                    trade_phone=detail['phone'],
        #                                    trade_nickname=detail['nickname'],
        #                                    province_code=detail['province_code'],
        #                                    city_code=detail['city_code'],
        #                                    district_code=detail['district_code'],
        #                                    invite_code=detail['invite_code'],
        #                                    couponid=detail['coupon_id'],
        #                                    buyer_id=detail['buyer_id'],
        #                                    order_detail=json.dumps(detail['order_detail'])
        #                                    )
        #             pre_params = {
        #                 'body': body,
        #                 'out_trade_no': tradeno,
        #                 'total_fee': int(float(total_fee) * 100),  # 微信规定以分为单位
        #                 'spbill_create_ip': client_ip,
        #             }
        #             # mobile浏览器&非微信浏览器
        #             if mweb == 1:
        #                 payObj = WeChatPay('qrh5')
        #             # mobile浏览器&微信浏览器
        #             elif mweb == 2:
        #                 payObj = WeChatPay('mp')
        #                 pre_params['openid'] = openid
        #             # PC浏览器
        #             else:
        #                 payObj = WeChatPay('qrcode')
        #             params = payObj.build_form_by_params(pre_params)
        #             if params:
        #                 tradeObj.save()
        #             return {'retcode': 0, 'wechat_params': params, 'tradeno_yijiao': tradeno}

    # def user_purchase_exam_tmp(self, detail, tradeno, total_fee, client_ip, openid):
    #     """
    #     :param detail: 存放订单信息
    #     :param tradeno: 订单号
    #     :param total_fee: 总共金额数
    #     :param client_ip: 客户机ip
    #     :param openid: 微信公众号支付需要openid
    #     :return:
    #     """
    #
    #     """
    #     price, address, phone, nickname, product_id'
    #                                                   'invite_code, choice'
    #     """
    #
    #     tradeObj = WeChatTrade(tradeno_yijiao=tradeno,
    #                            body="",
    #                            deal_status=mm_WeChatTrade.TRADE_STATUS_UNPAY,
    #                            total_fee=total_fee,
    #                            trade_type='NATIVE',
    #                            fee_type='CNY',
    #                            device_info='WEB',
    #                            buyer_id=detail['buyer_id'],
    #                            content=json.dumps(detail)
    #                            )
    #
    #     pre_params = {
    #         'body': "智慧试卷订单",
    #         'out_trade_no': tradeno,
    #         'total_fee': int(float(total_fee) * 100),  # 微信规定以分为单位
    #         'spbill_create_ip': client_ip,
    #     }
    #     payObj = WeChatPay('mp')
    #     pre_params['openid'] = openid
    #     params = payObj.build_form_by_params(pre_params)
    #     if params:
    #         tradeObj.save()
    #     return {'retcode': 0, 'wechat_params': params, 'tradeno_yijiao': tradeno}
    #
    # def user_purchase_u_proxy(self, detail, tradeno, total_fee, client_ip, openid, body=None):
    #     """
    #     :param detail: 存放订单信息
    #     :param tradeno: 订单号
    #     :param total_fee: 总共金额数
    #     :param client_ip: 客户机ip
    #     :param openid: 微信公众号支付需要openid
    #     :param body
    #     :return:
    #     product_id', 'address', 'phone', 'nickname', 'province_code', 'city_code', 'district_code',
    #                     'content', buyer_id, goods_list
    #     """
    #
    #     tradeObj = WeChatTrade(tradeno_yijiao=tradeno,
    #                            body=body if body else detail['goods_list'],
    #                            deal_status=mm_WeChatTrade.TRADE_STATUS_UNPAY,
    #                            total_fee=total_fee,
    #                            trade_type='NATIVE',
    #                            fee_type='CNY',
    #                            device_info='WEB',
    #                            trade_address=detail['address'],
    #                            trade_phone=detail['phone'],
    #                            trade_nickname=detail['nickname'],
    #                            buyer_id=detail['buyer_id'],
    #                            province_code=detail['province_code'],
    #                            city_code=detail['city_code'],
    #                            district_code=detail['district_code'],
    #                            content=json.dumps(detail)
    #                            )
    #
    #     pre_params = {
    #         'body': "亿教课程订单",
    #         'out_trade_no': tradeno,
    #         'total_fee': int(float(total_fee) * 100),  # 微信规定以分为单位
    #         'spbill_create_ip': client_ip,
    #     }
    #     payObj = WeChatPay('mp')
    #     pre_params['openid'] = openid
    #     params = payObj.build_form_by_params(pre_params)
    #     if params:
    #         tradeObj.save()
    #     return {'retcode': 0, 'wechat_params': params, 'tradeno_yijiao': tradeno}
    #
    # def user_purchase_tmp(self, detail, tradeno, total_fee, body, client_ip, openid):
    #     """
    #     :param detail: 存放订单信息
    #     :param tradeno: 订单号
    #     :param total_fee: 总共金额数
    #     :param body: 订单内容
    #     :param client_ip: 客户机ip
    #     :param openid: 微信公众号支付需要openid
    #     :return:
    #     """
    #
    #     """
    #     price, address, phone, nickname, product_id'
    #                                                   'invite_code, choice'
    #     """
    #
    #     tradeObj = WeChatTrade(tradeno_yijiao=tradeno,
    #                            body=json.dumps(body),
    #                            deal_status=mm_WeChatTrade.TRADE_STATUS_UNPAY,
    #                            total_fee=total_fee,
    #                            trade_type='NATIVE',
    #                            fee_type='CNY',
    #                            device_info='WEB',
    #                            trade_address=detail['address'],
    #                            trade_phone=detail['phone'],
    #                            trade_nickname=detail['nickname'],
    #                            invite_code=detail['invite_code'],
    #                            buyer_id=detail['buyer_id'],
    #                            content=json.dumps(detail)
    #                            )
    #
    #     pre_params = {
    #         'body': "亿教课程订单",
    #         'out_trade_no': tradeno,
    #         'total_fee': int(float(total_fee) * 100),  # 微信规定以分为单位
    #         'spbill_create_ip': client_ip,
    #     }
    #     payObj = WeChatPay('mp')
    #     pre_params['openid'] = openid
    #     params = payObj.build_form_by_params(pre_params)
    #     if params:
    #         tradeObj.save()
    #     return {'retcode': 0, 'wechat_params': params, 'tradeno_yijiao': tradeno}
